package com.company.anr.service;

import com.company.anr.config.AnrConfig;
import com.company.anr.model.AnalysisRequest;
import com.company.anr.model.AnalysisResponse;
import com.company.anr.utils.SnValidator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Value;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

@Service
public class AnrAnalysisService {

  private static final Logger logger = LoggerFactory.getLogger(AnrAnalysisService.class);

  @Autowired
  private WebAutomationService webAutomationService;

  @Autowired
  private FileProcessingService fileProcessingService;

  @Autowired
  private AnrConfig anrConfig;

  @Value("${download.directory:${anr.work.directory}}")
  private String downloadDirectory;

  /**
   * 执行完整的ANR分析流程
   * 
   * @param request 分析请求
   * @return 分析响应
   */
  public AnalysisResponse analyzeDevice(AnalysisRequest request) {
    logger.info("开始分析设备: {}", request.getDeviceSn());

    try {
      // 验证SN格式
      if (!SnValidator.isValid(request.getDeviceSn())) {
        String error = SnValidator.getValidationError(request.getDeviceSn());
        return new AnalysisResponse(false, error);
      }

      // 检查是否为测试模式
      // 因为浏览器那边一直不能把压缩包下载下来，这里解析本地的压缩包来测试后面的解析文件的方法
      if (request.getDeviceSn().startsWith("test")) {
        return analyzeDeviceTestMode(request);
      }

      // 初始化浏览器
      if (!webAutomationService.isInitialized()) {
        webAutomationService.initializeBrowser();
      }

      // 登录
      webAutomationService.login(request.getUsername(), request.getPassword());

      // 下载日志
      String filename = webAutomationService.downloadDeviceLogsPythonStyle(request.getDeviceSn(), request.getPhone());
      if (filename == null) {
        return new AnalysisResponse(false, "日志下载失败");
      }

      logger.info("日志下载成功，文件名: {}", filename);

      // 处理文件
      Path baseDir = Paths.get(downloadDirectory);
      Path detailDir = Paths.get(anrConfig.getDetailDirectory());
      Path zipFile = baseDir.resolve(filename);
      Path outputDir = Paths.get(anrConfig.getWorkPathForSn(request.getDeviceSn()));

      // 创建DETAIL目录（如果不存在）
      Files.createDirectories(detailDir);

      // 等待文件完全下载
      int maxWaitTime = 60; // 最多等待60秒
      int waitTime = 0;
      while (!Files.exists(zipFile) && waitTime < maxWaitTime) {
        try {
          Thread.sleep(1000);
          waitTime++;
          logger.info("等待文件下载完成... ({}/{})", waitTime, maxWaitTime);
        } catch (InterruptedException e) {
          Thread.currentThread().interrupt();
          return new AnalysisResponse(false, "等待文件下载时被中断");
        }
      }

      if (!Files.exists(zipFile)) {
        logger.error("下载的文件不存在: {}", zipFile);
        return new AnalysisResponse(false, "下载的文件不存在: " + zipFile);
      }

      logger.info("文件下载完成，开始解压和处理: {}", zipFile);

      // 按:
      // 1. /anr 目录下的各APP文件夹下的各block_xxxx_blockinfo.txt文件内容贴出；
      // 2. /system/anr 目录下的各anr_xxx文件内容贴出。

      // 按1,2的规则解析要的日志
      boolean success = fileProcessingService.extractAndCopy(zipFile, baseDir, outputDir);

      if (success) {
        // 生成分析报告到DETAIL目录
        Path anrFolder = outputDir.resolve("anr");
        Path detailReportFile = Paths.get(anrConfig.getDetailReportPathForSn(request.getDeviceSn()));

        if (Files.exists(anrFolder)) {
          fileProcessingService.processAnrFolder(anrFolder, detailReportFile);
          logger.info("分析报告已生成: {}", detailReportFile);
        } else {
          // 即使没有anr文件夹，也要生成analysis.txt文件
          logger.info("anr文件夹不存在，生成无ANR日志报告");
          fileProcessingService.generateNoAnrReport(detailReportFile);
          logger.info("无ANR日志报告已生成: {}", detailReportFile);
        }

        List<String> generatedFiles = fileProcessingService.getGeneratedFiles(outputDir);
        String message = String.format("设备 %s 日志分析成功", request.getDeviceSn());

        AnalysisResponse response = new AnalysisResponse(true, message,
            request.getDeviceSn(), outputDir.toString(), generatedFiles);

        logger.info("设备 {} 分析完成，生成文件: {}", request.getDeviceSn(), generatedFiles.size());
        return response;
      } else {
        return new AnalysisResponse(false, "文件处理失败");
      }

    } catch (Exception e) {
      logger.error("分析设备 {} 时出错: {}", request.getDeviceSn(), e.getMessage());
      AnalysisResponse response = new AnalysisResponse(false, "分析过程中发生错误: " + e.getMessage());
      response.setErrorDetails(e.getMessage());
      return response;
    }
  }

  /**
   * 检查是否为测试模式
   */
  private boolean isTestMode(String deviceSn) {
    // 如果设备SN以"test"开头，则使用测试模式
    return deviceSn.startsWith("test");
  }

  /**
   * 测试模式分析设备
   */
  private AnalysisResponse analyzeDeviceTestMode(AnalysisRequest request) {
    logger.info("使用测试模式分析设备: {}", request.getDeviceSn());

    try {
      // 创建输出目录
      Path baseDir = Paths.get(downloadDirectory);
      Path detailDir = Paths.get(anrConfig.getDetailDirectory());
      Path outputDir = Paths.get(anrConfig.getWorkPathForSn(request.getDeviceSn()));

      Files.createDirectories(detailDir);
      Files.createDirectories(outputDir);

      // 查找可用的测试数据
      Path testDataDir = findTestDataDirectory();
      if (testDataDir == null) {
        return new AnalysisResponse(false, "未找到测试数据目录，请检查以下路径是否存在：\n" +
            "- D:/pycharam/2025-9-12\n" +
            "- D:/ANR-WORK\n" +
            "- 当前工作目录下的测试数据");
      }

      logger.info("使用测试数据目录: {}", testDataDir);

      // 查找匹配的测试数据
      Path deviceDir = findMatchingTestData(testDataDir, request.getDeviceSn());
      if (deviceDir == null) {
        return new AnalysisResponse(false, "未找到匹配的测试数据，请检查SN: " + request.getDeviceSn() +
            "\n可用测试数据: " + listAvailableTestData(testDataDir));
      }

      logger.info("找到匹配的测试数据: {}", deviceDir);

      // 复制现有数据到输出目录
      fileProcessingService.copySnUsefulFolders(deviceDir, outputDir);

      // 生成分析报告
      Path anrFolder = outputDir.resolve("anr");
      Path detailReportFile = detailDir.resolve(request.getDeviceSn() + "_analysis.txt");

      if (Files.exists(anrFolder)) {
        fileProcessingService.processAnrFolder(anrFolder, detailReportFile);
        logger.info("测试模式分析报告已生成: {}", detailReportFile);
      } else {
        // 即使没有anr文件夹，也要生成analysis.txt文件
        logger.info("测试模式：anr文件夹不存在，生成无ANR日志报告");
        fileProcessingService.generateNoAnrReport(detailReportFile);
        logger.info("测试模式无ANR日志报告已生成: {}", detailReportFile);
      }

      List<String> generatedFiles = fileProcessingService.getGeneratedFiles(outputDir);
      String message = String.format("设备 %s 测试模式分析成功", request.getDeviceSn());

      AnalysisResponse response = new AnalysisResponse(true, message,
          request.getDeviceSn(), outputDir.toString(), generatedFiles);

      logger.info("设备 {} 测试模式分析完成，生成文件: {}", request.getDeviceSn(), generatedFiles.size());
      return response;

    } catch (Exception e) {
      logger.error("测试模式分析设备 {} 时出错: {}", request.getDeviceSn(), e.getMessage());
      return new AnalysisResponse(false, "测试模式分析失败: " + e.getMessage());
    }
  }

  /**
   * 查找测试数据目录
   */
  private Path findTestDataDirectory() {
    // 按优先级查找测试数据目录
    String[] possiblePaths = {
        "D:/pycharam/2025-9-12",
        "D:/ANR-WORK",
        "D:/test-data",
        "test-data"
    };

    for (String pathStr : possiblePaths) {
      Path path = Paths.get(pathStr);
      if (Files.exists(path) && Files.isDirectory(path)) {
        return path;
      }
    }

    return null;
  }

  /**
   * 查找匹配的测试数据
   */
  private Path findMatchingTestData(Path testDataDir, String deviceSn) {
    try {
      // 首先尝试精确匹配
      Path exactMatch = testDataDir.resolve(deviceSn);
      if (Files.exists(exactMatch) && Files.isDirectory(exactMatch)) {
        return exactMatch;
      }

      // 如果精确匹配失败，查找包含SN的目录
      return Files.list(testDataDir)
          .filter(Files::isDirectory)
          .filter(dir -> dir.getFileName().toString().contains(deviceSn))
          .findFirst()
          .orElse(null);

    } catch (IOException e) {
      logger.error("查找测试数据时出错: {}", e.getMessage());
      return null;
    }
  }

  /**
   * 列出可用的测试数据
   */
  private String listAvailableTestData(Path testDataDir) {
    try {
      return Files.list(testDataDir)
          .filter(Files::isDirectory)
          .map(dir -> dir.getFileName().toString())
          .collect(java.util.stream.Collectors.joining(", "));
    } catch (IOException e) {
      return "无法列出测试数据";
    }
  }

  /**
   * 清理资源
   */
  public void cleanup() {
    try {
      webAutomationService.closeBrowser();
      logger.info("资源清理完成");
    } catch (Exception e) {
      logger.error("资源清理时出错: {}", e.getMessage());
    }
  }

  /**
   * 检查服务状态
   * 
   * @return 服务状态信息
   */
  public String getServiceStatus() {
    if (webAutomationService.isInitialized()) {
      return "服务已初始化，浏览器已启动";
    } else {
      return "服务未初始化";
    }
  }

  /**
   * 处理已下载的文件 - 解压、重命名、解析ANR日志
   * 
   * @param deviceSn 设备SN
   * @return 处理结果
   */
  public AnalysisResponse processDownloadedFile(String deviceSn) {
    logger.info("开始处理已下载的文件 - SN: {}", deviceSn);

    try {
      // 验证SN格式
      if (!SnValidator.isValid(deviceSn)) {
        String error = SnValidator.getValidationError(deviceSn);
        return new AnalysisResponse(false, error);
      }

      Path baseDir = Paths.get(anrConfig.getWorkDirectory());
      Path detailDir = Paths.get(anrConfig.getDetailDirectory());
      Path outputDir = Paths.get(anrConfig.getProcessedPathForSn(deviceSn));

      // 创建DETAIL目录（如果不存在）
      Files.createDirectories(detailDir);

      // 查找下载目录中的压缩包文件
      Path zipFile = findDownloadedZipFile(baseDir, deviceSn);
      if (zipFile == null) {
        return new AnalysisResponse(false, "未找到下载的压缩包文件，请确保文件已下载到: " + baseDir);
      }

      logger.info("找到下载的压缩包文件: {}", zipFile);

      // 按规则解析日志
      boolean success = fileProcessingService.extractAndCopy(zipFile, baseDir, outputDir);

      if (success) {
        // 生成分析报告到DETAIL目录
        Path anrFolder = outputDir.resolve("anr");
        Path detailReportFile = Paths.get(anrConfig.getDetailReportPathForSn(deviceSn));

        if (Files.exists(anrFolder)) {
          fileProcessingService.processAnrFolder(anrFolder, detailReportFile);
          logger.info("分析报告已生成: {}", detailReportFile);
        } else {
          // 即使没有anr文件夹，也要生成analysis.txt文件
          logger.info("anr文件夹不存在，生成无ANR日志报告");
          fileProcessingService.generateNoAnrReport(detailReportFile);
          logger.info("无ANR日志报告已生成: {}", detailReportFile);
        }

        // 创建以SN命名的文件夹并复制文件
        Path snParentDir = Paths.get(anrConfig.getProcessedDirectory());
        Files.createDirectories(snParentDir);
        Path snFolder = fileProcessingService.createSnFolderAndCopyFiles(outputDir, snParentDir.resolve(deviceSn));
        logger.info("已创建SN文件夹: {}", snFolder);

        List<String> generatedFiles = fileProcessingService.getGeneratedFiles(outputDir);
        String message = String.format("设备 %s 文件处理成功", deviceSn);

        AnalysisResponse response = new AnalysisResponse(true, message,
            deviceSn, outputDir.toString(), generatedFiles);

        logger.info("设备 {} 文件处理完成，生成文件: {}", deviceSn, generatedFiles.size());
        return response;
      } else {
        return new AnalysisResponse(false, "文件处理失败");
      }

    } catch (Exception e) {
      logger.error("处理已下载文件 {} 时出错: {}", deviceSn, e.getMessage());
      AnalysisResponse response = new AnalysisResponse(false, "文件处理过程中发生错误: " + e.getMessage());
      response.setErrorDetails(e.getMessage());
      return response;
    }
  }

  /**
   * 查找下载目录中的压缩包文件
   * 
   * @param baseDir  基础目录
   * @param deviceSn 设备SN
   * @return 压缩包文件路径，如果未找到则返回null
   */
  private Path findDownloadedZipFile(Path baseDir, String deviceSn) {
    try {
      // 查找所有可能的压缩包文件
      return Files.list(baseDir)
          .filter(Files::isRegularFile)
          .filter(path -> {
            String fileName = path.getFileName().toString().toLowerCase();
            return fileName.endsWith(".zip") || fileName.endsWith(".gz") || fileName.endsWith(".tar.gz");
          })
          .findFirst()
          .orElse(null);
    } catch (IOException e) {
      logger.error("查找压缩包文件时出错: {}", e.getMessage());
      return null;
    }
  }
}
